import java.text.SimpleDateFormat;
import java.util.*;
/**
 * 短作业优先调度算法工具类
 * @author MMMMM
 *
 */
public class ShortJobFirstUtil {
    private  static SimpleDateFormat tm= new SimpleDateFormat("HH:mm:ss");
    //作业初始化
    @SuppressWarnings("resource")
    public static Job init(Job job) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入作业名称：如（作业1）");
        job.setJobName(scanner.nextLine());
        System.out.println("请输入作业到达时间：如（1）");
        job.setJobArrivalTime(scanner.nextInt());
        System.out.println("请输入作业服务时间：如（3）");
        job.setJobServiceTime(scanner.nextInt());
        return job;
    }
    //按照服务时间去排序
    public static void sortByServerTime(List<Job> jobs){
        //使用Collections工具类中的自定义条件排序方法
        Collections.sort(jobs , new Comparator<Job>() {
            @Override
            public int compare(Job job1, Job job2) {
                return (int) (job1.getJobServiceTime() - job2.getJobServiceTime());
            }
        });
    }
    //按照到达时间去排序
    public static void sortByArrivalTime(List<Job> jobs){
        //使用Collections工具类中的自定义条件排序方法
        Collections.sort(jobs , new Comparator<Job>() {
            @Override
            public int compare(Job job1, Job job2) {
                return (int) (job1.getJobArrivalTime() - job2.getJobArrivalTime());
            }
        });
    }
    //调度算法函数，最终将需要按顺序执行的作业放入execJobs中
    //jobs，输入队列，
    //execJobs，执行队列
    public static List<Job> dispatchJob(List<Job> jobs,List<Job> execJobs){
        //中间队列，暂存从输入队列中挑选出的作业
        List<Job> tempJobs = new ArrayList<>();
        //cpu无工作时，第一个到达的作业先服务，结束时间前到达的作业在执行
        ShortJobFirstUtil.sortByArrivalTime(jobs);
        execJobs.add(jobs.get(0));
        jobs.remove(jobs.get(0));
        //将输入队列中的作业一个一个的移动到执行队列中
        while (jobs.size()>0) {
            //execJobs队列的最后一个exexJob的结束时间
            Job exexJob = execJobs.get((execJobs.size() - 1));
            int endTime = exexJob.getJobArrivalTime() + exexJob.getJobServiceTime();
            //使用迭代器，便于输入队列的删除，不会出错
            Iterator<Job> iterator = jobs.iterator();
            //迭代判断
            while (iterator.hasNext()){
                Job job = iterator.next();
                //将执行队列中的结束时间大于输入队列的到达时间的所有作业移动到执行队列
                if (endTime >= job.getJobArrivalTime()) {
                    tempJobs.add(job);
                    iterator.remove();
                }
            }
            //若遍历后，执行队列结束时间还没有作业到达，则按照到达时间排序得到第一个
            if (tempJobs==null){
                ShortJobFirstUtil.sortByArrivalTime(jobs);
                execJobs.add(jobs.get(0));
                jobs.remove(jobs.get(0));
            }
            //按照服务时间长短进行排序，便于下面移动到执行队列的作业的顺序不出错
            ShortJobFirstUtil.sortByServerTime(tempJobs);
            execJobs.addAll(tempJobs);
            tempJobs.clear();
        }
        return execJobs;
    }
    //求出周转时间,平均周转时间等其他信息
    public static void turnRoundTime(List<Job> jobs){
        //第一个的到达时间
        int temp = jobs.get(0).getJobArrivalTime();
        for (Job job : jobs){
            //如果前一个作业的结束时间小于当前作业的到达时间
            if (temp < job.getJobArrivalTime()){
                temp = job.getJobArrivalTime();
            }
            //设置作业的开始时间.前一个的结束时间等于本次的开始时间
            job.setJobStartTime(temp);
            //得到每个作业的服务时间
            int serviceTime = job.getJobServiceTime();
            temp+=serviceTime;
            //结束时间=开始时间+服务时间
            job.setJobOverTime(temp);
            //周转时间=结束时间-到达时间
            int turnRound = temp-job.getJobArrivalTime();
            job.setJobRoundTime(turnRound);
            //带权周转时间=周转时间/服务时间
            job.setJobAvgRoundTime((1.0*turnRound)/serviceTime);
        }
    }
    //输出作业运行时间
    public static void showTime(List<Job> jobs){
        System.out.println("作业名称\t\t到达时间\t\t服务时间\t\t开始时间\t\t结束时间\t\t周转时间\t\t带权周转时间");
        double turnRound = 0.0;
        double avgTurnRound = 0.0;
        for (Job job : jobs){
            System.out.println("\t"+job.getJobName()+"\t\t\t"+job.getJobArrivalTime()+"\t\t\t"+job.getJobServiceTime()
                    +"\t\t\t"+job.getJobStartTime()+"\t\t\t"+job.getJobOverTime()+"\t\t\t"+job.getJobRoundTime()
                    +"\t\t\t"+job.getJobAvgRoundTime());
            turnRound+=job.getJobRoundTime();
            avgTurnRound+=job.getJobAvgRoundTime();
        }
        System.out.println(jobs.size()+"个作业的平均周转时间为："+String.format("%g %n",(1.0*turnRound)/jobs.size()));
        System.out.println(jobs.size()+"个作业的平均带权周转时间为："+String.format("%g %n",(1.0*avgTurnRound)/jobs.size()));
    }
    //模拟作业到达时间的过程
    public static void sleepJob(List<Job> jobs){
        long l = System.currentTimeMillis();
        ShortJobFirstUtil.sortByArrivalTime(jobs);
        for (Job job : jobs){
            try {
                Thread.sleep(job.getJobArrivalTime()*1000);
                System.out.print("作业执行情况为："+job.getJobName()+"在"+tm.format(new Date())+"到达！");
                Thread.sleep(job.getJobServiceTime()*1000);
                System.out.println("---在"+tm.format(new Date())+"结束作业！");
            } catch (InterruptedException e) {
                System.out.println("系统出错！！请退出重试！！！");
            }
        }
    }
}